DID Auth: Scope, Formats, and Protocols

Markus Sabadello, Danube Tech (https://danubetech.com), Vienna, March 3rd 2018

Now as certain base technologies for decentralized identity are becoming more mature (e.g. DIDs), this seems to be a good time to work on some of the most basic uses of these building blocks – such as using DIDs for authentication. There is broad interest from many individuals and organizations around the world in this topic.

This paper is intended as an overview and outline to frame the discussion about DID Auth at RWoT#6.

Scope

The term DID Auth has been used for different things and is currently not really well-defined.

At a minimum, it should be understood as "proving control over a DID" in one way or another.

This can take place using a number of different formats, protocols, and flows.

In addition to "proving control over a DID", DID Auth could potentially also be understood more broadly as "proving something else such as possession of a credential". Or to put it another way, "control over a DID" is a special claim – the most fundamental self-asserted claim that "I am me" – that an identity owner would want to prove. "Proving something else such as possession of a credential" could therefore be considered an extension of basic DID Auth.

DID Auth Basics

What all variants of DID Auth have in common is that during an interaction between an identity owner and a relying party, the identity owner proves control over a DID.

This requires the following steps to be executed by the relying party:

DID Auth must be understood to be extensible with regard to how an identity owner can prove control over a DID (not just through cryptographic signatures).

DID Auth must also be understood to work with multiple types of public keys.

Example DID Document with authentication and publicKey objects:

{
    "@context": "https://w3id.org/did/v1",
    "id": "did:example:123456789abcdefghi",
    "authentication": [{
        "type": "RsaSignatureAuthentication2018",
        "publicKey": "did:example:123456789abcdefghi#keys-1"
    }, {
        "type": "Ed25519SignatureAuthentication2018",
        "publicKey": "did:example:123456789abcdefghi#keys-2"
    }],
    "publicKey": [{
        "id": "did:example:123456789abcdefghi#keys-1",
        "type": "RsaVerificationKey2018",
        "owner": "did:example:123456789abcdefghi",
        "publicKeyPem": "-----BEGIN PUBLIC KEY...END PUBLIC KEY-----\r\n"
    }, {
        "id": "did:example:123456789abcdefghi#keys-2",
        "type": "Ed25519VerificationKey2018",
        "owner": "did:example:123456789abcdefghi",
        "publicKeyBase58": "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV"
    }]
}

In some variants of DID Auth, an identity owner's proof of control over a DID is preceded by a cryptographic challenge issues by a relying party to an identity ower, and again in some variants, this challenge is delivered to the identity owner via a DID Auth service endpoint in the DID Document.

Example DID Document:

{
    "@context": "https://w3id.org/did/v1",
    "id": "did:example:123456789abcdefghi",
    "service": {
        "type": "DidAuthService",
        "serviceEndpoint": "https://auth.example.com/did:example:123456789abcdefg"
    }
}

In the DID resolution process, it is currently assumed that a DID resolver returns an entire DID Document for a given DID. One optimization could be to define input parameters to a DID resolution process that would return not a full DID Document, but only the parts that are needed for a DID Auth process, e.g. the authentication and publicKey objects, and a DID Auth service endpoint.

References:

Types of DID Auth

Proving control over a DID by an identity owner to a relying party can take place using a number of different formats, protocols, and flows.

The following sections are an attempt to enumerate and group some of these variants.

DID-Auth'ed Channels

It is possible to establish authenticated (and potentially encrypted) communication channels between two parties that each act as both identity owner and relying party. Both parties of the channel are mutually authenticated. Establishment of such a channel takes place before any additional payloads are exchanged between the parties. In order to establish an authenticated channel, one party generally knows the endpoint for such a channel to the other party in advance, or this endpoint may be discoverable from the party's DID.

DID-TLS

References:

Intermediary DID-TLS

References:

CurveZMQ

References:

DID-Auth'ed Isolated Messages

An isolated message outside of an established channel may include a proof by an identity owner.

HTTP Signatures

Example:

POST /api/v1/issuerservices HTTP/1.1
Host: django-devex-von-test.pathfinder.gov.bc.ca
User-Agent: curl/7.58.0
Accept: */*
Authorization: Signature keyId="did:example:123456789abcdefghi#keys-1",algorithm="rsa-sha256",headers="(request-target) accept user-agent",signature="214BeK0YJ9P2wmMXBjZNNXDMT4prNlc32ZkslillkJYkJeLp3zbz4r1WfgCltd103m7AyY734qbau+GsWENDXaqxeTaP6LSMLWr6FexWMVgBbMzH1KDMhJlozTMFPkMsGlbuDpRKwEPqnX1Yy6ldHLe8mIJfSAEUy5P/Hf3y1b1kI8XyHNVbChFJLiUkOocF7XsFuTfoB+MJSEUqJDnuKibiF+Ap9rxI7J7Uroe6EjaVYqLXnGbpu8j8Oxn5QzGBZFCA/j6XgHy4NK9fG9pcCyyAPGzSYi1RWjDWFyS0RDQAXFBBNgyskXAgssKuVS2AFwPvXcHb5mhvKFUYMvMESg=="

References:

E-mail Signatures

DID-Auth'ed Challenges/Responses

The most flexible variants of DID Auth are those where a challenge is issued by a relying party to an identity owner, who answers with a response to the relying party. This response proves control over a DID (e.g. with a cryptographic signature) and is linked to the challenge (e.g. with a nonce and timestamp).

Formats, protocols, and flows:

Composition of components:

Additional considerations:

References:

Example Flow 1

  1. Relying party's mobile web page redirects via deep link (with challenge) to identity owner's mobile app.
  2. Identity owner's mobile app opens link (with response) to relying party's web server. OR:
  3. Identity owner's mobile app sends HTTP POST (with response) to relying party's web server.

Example challenge:

did:auth?challenge=...

Example response:

{
    "header": {
        "typ": "JWT",
        "alg": "ES256"
    },
    "payload": {
        "iss": "did:example:123456789abcdefg",
        "sub": "did:example:123456789abcdefg",
        iat: 1479850830,
        exp: 1511305200,
    },
    "signature": "..."
}

References:

Example Flow 2

  1. Relying party's web page displays a QR code (with challenge) that is scanned by identity owner's mobile app.
  2. Identity owner's mobile app sends HTTP POST (with response) to relying party's web server.
  3. { Relying party's web server sends push notification (with response) to relying party's web page. }

Example challenge:

{
    "header": {
        "typ": "JWT",
        "alg": "ES256"
    },
    "payload": {
        "iss": "did:example:123456789abcdefg",
        "callback": "https://rp.example.com/didauth",
        "iat": "2018-01-01T12:42:26.556Z",
        "exp": "2018-01-01T13:32:26.556Z",
        "jti": "0.dqh8o13bnbs"
    },
    "signature": "..."
}

Example Flow 3

  1. Relying party's web page calls JavaScript function (with challenge) on identity owner's web browser.
  2. Identity owner's web browser communicates (with challenge and response) with identity owner's additional components such as a credential repository service. }
  3. Identity owner's web browser triggers JavaScript promise (with response) on relying party's web page.

Example challenge:

const credential = await navigator.credentials.get({
    web: {
        VerifiableProfile: {
        ...
        }
    }
});

Example response:

{
    "id": "http://example.gov/credentials/3732",
    "type": ["Credential", "IamMeCredential"],
    "issuer": "did:example:123456789abcdefghi",
    "issued": "2010-01-01",
    "claim": {
        "id": "did:example:123456789abcdefghi",
        "publicKey": "did:example:123456789abcdefghi#keys-2"
    },
    "proof": {
        "type": "Ed25519Signature2018",
        "created": "2018-01-01T21:19:10Z",
        "creator": "did:example:123456789abcdefghi#keys-2",
        "nonce": "c0ae1c8e-c7e7-469f-b252-86e6a0e7387e",
        "signatureValue": "..."
    }
}

References:

Example Flow 4

  1. Relying party's web page contains a link or button that redirects (with challenge) to identity owner's DID Auth web server.
  2. Identity owner's DID Auth web server communicates with identity owner's web browser. }
  3. Identity owner's DID Auth web server contains a link or button that redirects (with response) to relying party's web server.

Example challenge:

<form action="https://auth.example.com/did:example:123456789abcdefg" method="post">
    <input type="hidden" name="challenge" value="...">
    <input type="submit" value="Submit!">
</form>

Example Flow 5

  1. Relying party's mobile app displays a QR code (with challenge) that is scanned by identity owner's mobile app.
  2. Identity owner's mobile app sends HTTP POST (with response) to relying party's DID Auth service.
  3. Relying party's DID Auth service sends push notification (with response) to relying party's mobile app. }

Example Flow 6

  1. { Relying party's web page contains a link or button that calls the relying party's web server. }
  2. Relying party's web server sends HTTP POST (with challenge) to identity owner's DID Auth service.
  3. { Identity owner's DID Auth service sends push notification (with challenge) to identity owner's mobile app. }
  4. Identity owner's mobile app sends HTTP POST (with response) to relying party's web server.

Example Flow 7

  1. { Relying party's web page contains a link or button that calls the relying party's web server. }
  2. Relying party's web server sends HTTP POST (with challenge) to identity owner's DID Auth service.
  3. { Identity owner's DID Auth service sends push notification (with challenge) to identity owner's mobile app. }
  4. { Identity owner's mobile app sends HTTP POST (with response) to identity owner's DID Auth service. }
  5. Identity owner's DID Auth service sends HTTP POST (with response) to relying party's web server.

Next Steps

DID Auth work should focus on the following: